package com.example.librarymanagement.controller;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.example.librarymanagement.dto.user.UserAddDto;
import com.example.librarymanagement.dto.user.UserListDto;
import com.example.librarymanagement.dto.user.UserPasswordDto;
import com.example.librarymanagement.dto.user.UserUpdDto;
import com.example.librarymanagement.entity.Role;
import com.example.librarymanagement.entity.User;
import com.example.librarymanagement.entity.UserRole;
import com.example.librarymanagement.exception.BizException;
import com.example.librarymanagement.result.ResultCode;
import com.example.librarymanagement.service.IRoleService;
import com.example.librarymanagement.service.IUserRoleService;
import com.example.librarymanagement.service.IUserService;
import com.example.librarymanagement.util.CheckEntityUtil;
import com.example.librarymanagement.util.Const;
import com.example.librarymanagement.util.EnumConst;
import com.example.librarymanagement.vo.UserVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.security.Principal;
import java.time.LocalDateTime;
import java.util.*;

/**
 * @author ZHB
 */

@Api(tags = "用户模块")
@RestController
@RequestMapping("/sys/user")
public class UserController  extends BaseController  {

    @Resource
    private PasswordEncoder passwordEncoder;

    @GetMapping
    @PreAuthorize("hasAuthority('sys:user:list')")
    @ApiOperation(value = "查询用户分页列表")
    IPage<UserVo> getUserListPage(@Validated UserListDto userListDto) {
        IPage<UserVo> userList = userService.getUserList(userListDto);

        userList.getRecords().forEach(userVo -> {
            userVo.setRoles(roleService.getRoleListByUserId(userVo.getId()));
        });
        return userList;
    }

    @GetMapping("/list")
    @PreAuthorize("hasAuthority('sys:user:list')")
    @ApiOperation(value = "查询用户")
    List<User> getUserList() {
        return userService.list();
    }

    @PostMapping
    @ApiOperation(value = "新增用户")
    @PreAuthorize("hasAuthority('sys:user:save')")
    void addUser(@Validated @RequestBody UserAddDto userDto) {
        CheckEntityUtil.isNotNullByColumnEq("email", userDto.getEmail(), userService, ResultCode.USER_EMAIL_EXIST);
        CheckEntityUtil.isNotNullByColumnEq("username", userDto.getUsername(), userService, ResultCode.USER_USERNAME_EXIST);
        User user = new User();
        userDto.convertToEntity(user);
        user.setCreated(LocalDateTime.now());
        user.setState(EnumConst.STATE_AVAILABLE.getCode());
        user.setPassword(Const.DEFAULT_PASSWORD);
        if (StrUtil.isBlank(user.getPassword())) {
            throw new IllegalArgumentException("密码不能为空");
        }
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        userService.save(user);
    }

    @PutMapping
    @ApiOperation(value = "修改用户")
    @PreAuthorize("hasAuthority('sys:user:update')")
    void updUser(@Validated @RequestBody UserUpdDto userDto) {
        User user = CheckEntityUtil.isNullById(userDto.getId(), userService, ResultCode.USER_ACCOUNT_NOT_EXIST);
        userDto.convertToEntity(user);
        if (StrUtil.isNotBlank(user.getPassword())) {
            String password = passwordEncoder.encode(user.getPassword());
            user.setPassword(password);
        }
        user.setUpdated(LocalDateTime.now());

        userService.updateById(user);
    }


    @PostMapping("/password")
    @ApiOperation(value = "用户修改个人密码")
    void upUserPassword(@RequestBody UserPasswordDto userPasswordDto, Principal principal) {
        User user = CheckEntityUtil.isNullByColumnEq("username", principal.getName(), userService, ResultCode.USER_ACCOUNT_NOT_EXIST);

        boolean matches = passwordEncoder.matches(userPasswordDto.getCurrentPass(), user.getPassword());
        if (!matches) {
            throw new BizException(ResultCode.PASSWORD_ERROR);
        }
        user.setPassword(passwordEncoder.encode(userPasswordDto.getPassword()));
        user.setUpdated(LocalDateTime.now());

        userService.updateById(user);
    }

    @DeleteMapping
    @Transactional(rollbackFor = {Exception.class})
    @ApiOperation(value = "禁用用户")
    @PreAuthorize("hasAuthority('sys:user:delete')")
    void delUser(String ids) {
        List<Integer> userIds = Arrays.asList(Convert.toIntArray(ids));
        userService.removeByIds(userIds);
        userRoleService.remove(new QueryWrapper<UserRole>().in("user_id", userIds));
    }

    @GetMapping("/info/{id}")
    @PreAuthorize("hasAuthority('sys:user:list')")
    public User info(@PathVariable Integer id) {
        User user = CheckEntityUtil.isNullById(id, userService, ResultCode.USER_ACCOUNT_NOT_EXIST);
        List<Role> roleList = roleService.getRoleListByUserId(id);
        user.setRoles(roleList);
        return user;
    }

    @GetMapping("/info")
    @ApiOperation(value = "获取当前登录用户信息")
    UserVo getUserInfo(Principal principal) {
        User user = userService.getUserByUsername(principal.getName());

        UserVo userVo = new UserVo();
        userVo.setId(user.getId());
        userVo.setUsername(user.getUsername());
        userVo.setEmail(user.getEmail());
        userVo.setPhone(user.getPhone());
        userVo.setState(user.getState());
        userVo.setLastLogin(user.getLastLogin());
        userVo.setCreated(user.getCreated());
        return userVo;
    }

    @PostMapping("/role/{id}")
    void userRole(@PathVariable(name = "id") Integer userId, @RequestBody Integer[] roleIds) {
        List<UserRole> userRoles = new ArrayList<>();

        for (Integer roleId : roleIds) {
            UserRole userRole = new UserRole();
            userRole.setUserId(userId);
            userRole.setRoleId(roleId);
            userRoles.add(userRole);
        }
        userRoleService.remove(new QueryWrapper<UserRole>().eq("user_id", userId));
        userRoleService.saveBatch(userRoles);

        User user = userService.getById(userId);
        userService.clearUserAuthorityInfo(user.getUsername());
    }

    @PostMapping("/repass")
    void repass(@RequestBody Integer userId) {
        User user = CheckEntityUtil.isNullById(userId, userService, ResultCode.USER_ACCOUNT_NOT_EXIST);
        String password = passwordEncoder.encode(user.getPassword());
        user.setPassword(password);
        user.setUpdated(LocalDateTime.now());
        userService.updateById(user);
    }
}


